<template>
	<view class="flex-box">
		<view class="title">我的网盘文件</view>
		<view class="history">
			<view class="flex">
				<view class="flex pointer" v-if="pathList.length>0" @click="pathBack()">
					<van-icon name="revoke" />
					<text>返回</text>
				</view>
				<view class="flex ml-10">
					<text>当前目录：</text>
					<text class="pointer" @click="toHomePath()">根目录</text>
					<template v-for="item in pathList">
						<text class="ml-4 mr-4">|</text>
						<text class="pointer" @click="pathBack(item)">{{item.name}}</text>
					</template>
				</view>
			</view>
			<view class="flex" @click="refreshList()">
				<van-icon name="replay" />
				<text>刷新</text>
			</view>
		</view>
		<view class="content">
			<unicloud-db ref="udb" v-slot:default="{data, loading, error, options}" collection="a-cloud-file" :where="where"
				orderby="isFolder desc,createdTime desc">
				<view v-if="error">{{error.message}}</view>
				<view v-else>
					<self-loading v-if="loading" height="50vh" />

					<van-checkbox-group v-model="selectFileList" class="list" v-else-if="data&&data.length>0">
						<view v-for="item in data" :key="item._id">
							<!-- 批量删除,使用不带气泡的 -->
							<view v-show="deleteMore" :actions="item.isFolder?actions:actions2" @click="onSelect($event,item)" overlay
								overlay-class="self-overlay">
								<folderOrFile :item="item" :deleteMore="deleteMore"></folderOrFile>
							</view>

							<!-- 带气泡选项 -->
							<van-popover v-if="!deleteMore" :actions="item.isFolder?actions:actions2" @select="onSelect($event,item)"
								overlay overlay-class="self-overlay">
								<template #reference>
									<folderOrFile :item="item"></folderOrFile>
								</template>
							</van-popover>
						</view>
					</van-checkbox-group>

					<no-data v-else />
				</view>
			</unicloud-db>
		</view>
		<view class="btn-box">
			<van-button class="mr-10" icon="plus" type="success" size="small" @click="addFolder()">新建文件夹</van-button>
			<van-button class="mr-10" icon="delete-o" type="danger" size="small" @click="deleteMore = true"
				v-if="!deleteMore">批量删除</van-button>
			<template v-else>
				<van-button class="mr-10" icon="delete-o" type="danger" size="small" @click="selectFile()"
					:disabled="selectFileList.length===0">{{selectFileList.length===0?'请选择文件':`确认删除(${selectFileList.length})`}}</van-button>
				<van-button class="mr-10" type="default" size="small" @click="deleteCancel()">取消删除</van-button>
			</template>
			<van-button icon="plus" type="primary" size="small" @click="selectImage()">上传</van-button>
		</view>

		<!-- 弹窗详情 -->
		<view>
			<van-popup v-model:show="popup.show" position="right" round z-index="998"
				style="height: 100vh; width: 400px;background: #f8f8f8;">
				<view>
					<van-cell-group title="查看文件详情"></van-cell-group>
				</view>
				<van-form @submit="onUpdate" class="form">
					<view class="image-show">
						<image v-if="['jpg','jpeg','png','gif','svg'].includes(popupItem.type)" width="280" height="280"
							mode="aspectFit" :src="popupItem.url" @click="previewImage(popupItem.url)" />
						<view class="detault-show" v-else>
							只能预览图片
						</view>
					</view>
					<van-cell-group inset>
						<van-field v-model="popupItem.splitName" name="splitName" label="文件名称" placeholder="文件名称"
							:rules="[{ required: true, message: '请填写文件名称' }]" input-align="right" />
						<van-cell title="格式" :value="popupItem.type"></van-cell>
						<van-cell title="大小" :value="popupItem.sizeStr"></van-cell>
						<van-cell title="文件操作">
							<template #right-icon>
								<view class="pointer" @click="copyTxt(popupItem.url)">
									<van-icon name="link-o" />
									<text class="ml-4">复制链接</text>
								</view>
								<view class="pointer ml-10" @click="downloadFile(popupItem.url,popupItem.name)">
									<van-icon name="down" />
									<text class="ml-4">下载文件</text>
								</view>
							</template>
						</van-cell>
						<van-cell title="创建时间" :value="moment(popupItem.createdTime)"></van-cell>
					</van-cell-group>
					<view class="form-btn">
						<van-button class="submit-btn mr-10" round block type="danger" size="small" @click="onDelete">
							删除文件
						</van-button>
						<van-button class="submit-btn" round block type="primary" size="small" native-type="submit">
							确认修改
						</van-button>
					</view>
				</van-form>

			</van-popup>
		</view>

		<!-- 新建文件夹 -->
		<van-popup v-model:show="addShow" position="center" round z-index="998" style="width: 400px;background: #f8f8f8;">
			<view>
				<van-cell-group title="新建文件夹"></van-cell-group>
			</view>
			<van-form @submit="confirmAddFolder" class="form">
				<van-cell-group inset>
					<van-field v-model="addFolderName" label="文件夹名称" placeholder="请输入"
						:rules="[{ required: true, message: '请输入文件夹名称' }]" input-align="right" />
				</van-cell-group>
				<view class="form-btn mb-20">
					<van-button class="submit-btn" round block type="primary" native-type="submit">
						确认新建
					</van-button>
				</view>
			</van-form>
		</van-popup>

		<!-- 重命名 -->
		<van-popup v-model:show="renameShow" position="center" round z-index="998"
			style="width: 400px;background: #f8f8f8;">
			<view>
				<van-cell-group
					:title="`重命名 [ ${renamePopupItem.splitName} ] ${renamePopupItem.isFolder?'文件夹':'文件'}`"></van-cell-group>
			</view>
			<van-form @submit="confirmRename" class="form">
				<van-cell-group inset>
					<van-field v-model="fileAndFolderRename" label="新的名称" placeholder="请输入"
						:rules="[{ required: true, message: '请输入新的名称' }]" input-align="right" />
				</van-cell-group>
				<view class="form-btn mb-20">
					<van-button class="submit-btn" round block type="primary" native-type="submit">
						确认修改
					</van-button>
				</view>
			</van-form>
		</van-popup>

	</view>
</template>

<script setup>
	import { reactive, ref, toRefs, computed } from 'vue';
	import { copyTxt, toast, modal, random, previewImage, downloadFile, moment, showLoading } from '@/utils/commen.js'
	const aFile = uniCloud.importObject('a-file')
	import { popupStore } from '@/store/vant';
	const db = uniCloud.database()
	const popup = new popupStore()

	const udb = ref()
	const udbData = ref([])
	const pathList = ref([])
	const where = computed(() => {
		let str = 'uid == $cloudEnv_uid'
		if (pathList.value.length > 0) {
			let copy = pathList.value[pathList.value.length - 1]
			str += `&& parentId == '${copy._id}'`
		} else {
			str += `&& parentId == ''`
		}
		return str
	})

	const show = ref(false);
	const deleteMore = ref(false)
	const popupItem = ref({})
	const selectFileList = ref([])

	const addShow = ref(false)
	const addFolderName = ref('')

	const renameShow = ref(false)
	const fileAndFolderRename = ref('')
	const renamePopupItem = ref({})

	const showPopover = ref(true)
	const actions = [
		{ text: '打开', code: "open", icon: 'share-o' },
		{ text: '重命名', code: "rename", icon: 'setting-o' },
		{ text: '删除', code: "delete", icon: 'delete-o' }
	]
	const actions2 = [
		{ text: '详情', code: "look", icon: 'share-o' },
		{ text: '复制链接', code: "copy", icon: 'setting-o' },
		{ text: '下载文件', code: "download", icon: 'setting-o' },
		{ text: '重命名', code: "rename", icon: 'setting-o' },
		{ text: '删除', code: "delete", icon: 'delete-o' }
	]
	// 确认选择
	function onSelect(e, item) {
		// 如果是批量删除模式,不需要打开文件详情
		if (deleteMore.value) {
			let index = selectFileList.value.indexOf(item)
			if (index !== -1) {
				selectFileList.value.splice(index, 1)
			} else {
				selectFileList.value.push(item)
			}
			return
		}

		if (e.code === 'look') {
			look(item)
		} else if (e.code === 'open') {
			pathList.value.push(item)
		} else if (e.code === 'copy') {
			copyTxt(item.url)
		} else if (e.code === 'download') {
			downloadFile(item.url, item.name)
		} else if (e.code === 'rename') {
			renamePopupItem.value = JSON.parse(JSON.stringify(item))
			renamePopupItem.value.splitName = renamePopupItem.value.name.split('.')[0]
			fileAndFolderRename.value = ''
			renameShow.value = true
		} else if (e.code === 'delete') {
			uni.showModal({
				title: '提示',
				content: `即将删除文件夹 [ ${item.name} ]`,
				success: async (r) => {
					if (!r.confirm) return
					try {
						uni.showLoading({ title: '请稍后' })
						// 删除文件夹
						if (item.isFolder) {
							// 查树形数据
							let { result: { data } } = await db.collection('a-cloud-file').get({
								getTree: {
									startWith: `parentId=='${item._id}'`
								}
							})
							// 递归为一维数组
							const layers = (list) => {
								let arr = []
								list.forEach(row => {
									arr.push({
										isFolder: row.isFolder ? true : false,
										_id: row._id,
										url: row.url || ''
									})
									if (row.children.length > 0) {
										arr = arr.concat(layers(row.children))
									}
								})
								return arr
							}
							let ddd = layers(data)
							// 加上本体文件夹
							ddd.push({
								isFolder: item.isFolder ? true : false,
								_id: item._id,
								url: item.url || ''
							})
							let folders = ddd.map(item=>item._id)
							await db.collection('a-cloud-file').where(`_id in ${JSON.stringify(folders)}`).remove()
							let urls = ddd.filter(item=>item.url).map(item=>item.url)
							await aFile.deleteFile(urls) // 删除云存储的源文件
							toast('删除成功')
							refreshList()
						}
						// 删除文件
						else {
							let { result } = await db.collection('a-cloud-file').where(`_id=='${item._id}'`).remove()
							toast('删除成功')
							refreshList()
						}
					} catch (error) {
						toast(`${error}`)
						console.log('error: ', error);
					} finally {
						uni.hideLoading()
					}
				}
			})
		}
	}
	
	// 返回首页路径
	function toHomePath(){
		pathList.value = []
		this.$next(()=>{
			refreshList()
		})
	}

	// 路径返回
	function pathBack(row) {
		let copy = JSON.parse(JSON.stringify(pathList.value))
		// 跳转到指定路径
		if (row && row._id) {
			let ids = copy.map(item => item._id)
			let index = ids.indexOf(row._id)
			copy = copy.splice(0, index)
			copy.push(row)
			pathList.value = copy
		}
		// 返回上一级
		else {
			copy.pop()
			pathList.value = copy
		}
	}

	// 重命名
	async function confirmRename() {
		let { isFolder, type } = renamePopupItem.value
		try {
			showLoading()
			let { result } = await db.collection('a-cloud-file')
				.where(`_id=='${renamePopupItem.value._id}'`)
				.update({
					name: fileAndFolderRename.value + (isFolder ? '' : `.${type}`)
				})
			renameShow.value = false
			toast('修改成功')
			refreshList()
		} catch (error) {
			toast(`重命名失败:${error}`)
			//TODO handle the exception
		}
	}

	// 查看文件
	function look(item) {
		// 如果是文件夹,也打断
		if (item.isFolder) {
			deleteMore.value = false
			selectFileList.value = []
			return
		}

		popupItem.value = JSON.parse(JSON.stringify(item))
		popupItem.value.splitName = popupItem.value.name.split('.')[0]

		const sizeType = data => {
			if (data / 1000 / 1000 / 1000 / 1000 > 1) {
				return (data / 1000 / 1000 / 1000 / 1000).toFixed(2) + 'Tb'
			} else if (data / 1000 / 1000 / 1000 > 1) {
				return (data / 1000 / 1000 / 1000).toFixed(2) + 'Gb'
			} else if (data / 1000 / 1000 > 1) {
				return (data / 1000 / 1000).toFixed(2) + 'Mb'
			} else if (data / 1000 > 1) {
				return (data / 1000).toFixed(2) + 'Kb'
			} else {
				return data.toFixed(2) + 'b'
			}
		}
		popupItem.value.sizeStr = sizeType(popupItem.value.size)
		popup.taggle()
	}

	// 新建文件夹
	function addFolder() {
		addShow.value = true
		addFolderName.value = ''
	}

	// 确认新建文件夹
	async function confirmAddFolder() {
		try {
			uni.showLoading({ title: '请稍后...' })
			let parentId = pathList.value.length > 0 ? pathList.value[pathList.value.length - 1]._id : ''
			let { result } = await db.collection('a-cloud-file')
				.add({
					parentId,
					name: addFolderName.value,
					isFolder: true
				})
			addShow.value = false
			uni.hideLoading()
			toast('新建成功')
			refreshList()
		} catch (error) {
			toast(`${error}`)
		}
	}

	// 刷新列表
	function refreshList() {
		udb.value.reset()
		udb.value.refresh()
	}

	// 修改文件
	async function onUpdate(values) {
		let { _id, type, splitName } = popupItem.value
		try {
			uni.showLoading({ title: '请稍后...' })
			let { result } = await db.collection('a-cloud-file')
				.where(`_id=='${_id}'`)
				.update({
					name: `${splitName}.${type}`
				})
			uni.hideLoading()
			toast('修改成功')
			popup.taggle()
			refreshList()
		} catch (error) {
			toast(`${error}`)
		}
	}

	// 删除单个文件
	function onDelete() {
		uni.showModal({
			title: '提示',
			content: `即将删除文件: [ ${popupItem.value.name} ] ,确定吗?`,
			complete: async (res) => {
				if (!res.confirm) return
				let d = await aFile.deleteFile(popupItem.value.url)
				try {
					uni.showLoading({ title: '请稍后...' })
					let { result } = await db.collection('a-cloud-file')
						.where(`_id=='${popupItem.value._id}'`)
						.remove()
					uni.hideLoading()
					toast('删除成功')
					popup.taggle()
					refreshList()
				} catch (error) {
					toast(`${error}`)
				}
			}
		})
	}

	// 取消批量删除
	function deleteCancel() {
		deleteMore.value = false
		selectFileList.value = []
	}

	// 批量删除文件
	async function selectFile() {
		uni.showModal({
			title: '提示',
			content: `即将删除 ${selectFileList.value.length} 个文件,确定吗?`,
			complete: async (res) => {
				if (!res.confirm) return
				let urls = selectFileList.value.map(item => item.url)
				let ids = selectFileList.value.map(item => item._id)
				deleteCancel()
				try {
					uni.showLoading({ title: '请稍后...' })
					let d = await aFile.deleteFile(urls)
					let r = await aFile.deleteOrder(ids, 'a-cloud-file')
					uni.hideLoading()
					toast('删除成功')
					refreshList()
				} catch (error) {
					toast(`${error}`)
					uni.hideLoading()
				}
			}
		})
	}

	// 选择文件准备上传
	function selectImage(e) {
		uni.chooseFile({
			type: 'all',
			complete: async (res) => {
				await uploadFunction(res)
			}
		})
	}

	// 开始上传
	async function uploadFunction(res) {
		if (res.tempFilePaths && res.tempFilePaths.length > 0) {
			res.tempFilePaths.forEach(async (path, index) => {
				try {
					uni.showLoading({ title: `正在上传${index+1}/${res.tempFilePaths.length}` })
					await uploadFileCurrent(path, res.tempFiles[index])
					uni.hideLoading()
				} catch (error) {
					console.log('error: ', error);
					modal(`上传第${index+1}个文件失败:${error}`)
				} finally {
					uni.hideLoading()
				}
			})
		}
	}

	// 上传单个文件
	async function uploadFileCurrent(filePath, fileObj) {
		return new Promise((resolve, reject) => {
			let { _id, username } = uni.getStorageSync('uni-id-pages-userInfo')
			let fileName =
				`${username}${new Date().getTime().toString().substring(7)}-${random(6)}.${fileObj.name.split('.').pop()}`
			uniCloud.uploadFile({
				filePath,
				cloudPath: `upload/${_id}/${fileName}`,
				cloudPathAsRealPath: true,
				success: async (result) => {
					let parentId = pathList.value.length > 0 ? pathList.value[pathList.value.length - 1]._id : ''
					let data = await db.collection('a-cloud-file').add({
						parentId,
						name: fileObj.name,
						size: fileObj.size,
						url: result.fileID,
						type: fileObj.name.split('.').pop()
					})
					refreshList()
					return resolve()
				},
				fail: (error) => {
					return reject(error)
				}
			})
		})

	}
</script>

<style lang="scss" scoped>
	.flex-box {
		display: flex;
		flex-direction: column;

		>.title {
			height: 42px;
			border-bottom: 1px solid #f1f1f1;
			display: flex;
			align-items: center;
			padding-left: 20px;
			font-size: 16px;
		}

		.content {
			flex: 1;
		}

		.btn-box {
			display: flex;
			justify-content: flex-end;
			align-items: center;
			padding: 10px;
		}
	}


	.list {
		display: flex;
		justify-content: flex-start;
		flex-wrap: wrap;
	}


	.self-action {
		::v-deep .van-popup {
			width: 360px !important;
			right: 0 !important;
			left: auto !important;
		}
	}

	.image-show {
		padding: 20px;
		display: flex;
		justify-content: center;
		align-items: center;
	}

	.detault-show {
		width: 280px;
		height: 180px;
		display: flex;
		justify-content: center;
		align-items: center;
		color: #666;
	}

	.form-btn {
		display: flex;
		justify-content: center;
		align-items: center;
		padding-top: 20px;

		.submit-btn {
			width: 120px;
		}
	}

	.history {
		height: 40px;
		border-bottom: 1px solid #f1f1f1;
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 0 12px;
		font-size: 14px;
		color: #555;
	}
</style>